﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using App_Code.Helpers;
using Rss;
using System.Text;
using PluginDB;

namespace App_Code.SiteParsers
{
    /// <summary>
    /// Summary description for PluginResponseGenerator
    /// </summary>
    public class PluginResponseGenerator
    {
        #region Protected Members
        private const int PAGE_SIZE = 20;
        private readonly CacheManager _cacheManager = CacheManager.Instance;
        private NameValueCollection _queryStringParams;
        private MenuItem.PluginMods _pluginMode;
        private MenuItem.FilterTypes _filterType;
        private int _pageNumber;

        private readonly Dictionary<int, string> _aTozListHeb = new Dictionary<int, string>();
        private readonly Dictionary<int, string> _aTozListEng = new Dictionary<int, string>();

        #endregion

        #region Protected Enum
        //protected enum PluginMode
        //{
        //    IDLE_MODE = 0,
        //    MOVIES_MODE,
        //    MOVIES_FILTER_MODE,
        //    SERIES_MODE,
        //    SERIES_FILTER_MODE,
        //    CATEGORIES_MODE,
        //    SEARCH_MODE,
        //    MOVIE_MODE,
        //    MOVIE_LINK_MODE
        //}

        //protected enum CategoriesMode
        //{
        //    CATEGORIES_MODE_LATEST = 200,
        //    CATEGORIES_MODE_ALL_CATEGORIES,
        //    CATEGORIES_MODE_A_TO_Z,
        //    CATEGORIES_MODE_BY_A_TO_Z_ID,
        //    CATEGORIES_MODE_HEB_SUB,
        //    CATEGORIES_MODE_HEB_DUB,
        //    CATEGORIES_MODE_SITES_FILTER,
        //    CATEGORIES_MODE_BY_ID,
        //    CATEGORIES_MODE_SITES_BY_ID
        //}
        #endregion

        #region Public Properties
        public string Url { get; set; }
        public string SearchText { get; set; }
        #endregion

        #region Public Methods
        public RssFeed Run(NameValueCollection queryStringParams)
        {
            try
            {
                this.InitMembers(queryStringParams);

                switch (_filterType)
                {
                    case MenuItem.FilterTypes.FILTER_TYPES_NO_FILTER:
                        {
                            return LoadIdleMenus();
                        }
                    default:
                        {
                            return LoadFiltersMenus();
                        }
                }
            }
            catch (Exception ex)
            {
                return CreateErrorResponse(ex.Message);
            }
        }
        #endregion

        #region Private Methods
        private void InitMembers(NameValueCollection queryStringParams)
        {
            this._queryStringParams = queryStringParams;
            this._pageNumber = Utils.GetParam(this._queryStringParams, Common.PAGE_NUMBER, 1);
            this._pluginMode = (MenuItem.PluginMods)Utils.GetParam(this._queryStringParams, Common.PLUGIN_MODE, (int)MenuItem.PluginMods.PLUGIN_MODE_IDLE_MODE);
            this._filterType = (MenuItem.FilterTypes)Utils.GetParam(this._queryStringParams, Common.FILTER_TYPE, (int)MenuItem.FilterTypes.FILTER_TYPES_NO_FILTER);
            this.Url = this._queryStringParams.ToString() == string.Empty ? this._pluginMode.ToString() : this._queryStringParams.ToString();
        }

        #region Build Main Menus
        private RssFeed LoadIdleMenus()
        {
            switch (this._pluginMode)
            {
                case MenuItem.PluginMods.PLUGIN_MODE_IDLE_MODE:
                    return LoadIdleMode();

                case MenuItem.PluginMods.PLUGIN_MODE_MOVIES:
                    return LoadMoviesMenu();

                case MenuItem.PluginMods.PLUGIN_MODE_SERIES:
                    return LoadSeriesMenu();

                default:
                    throw new Exception("Run Method got unexpected Mode");
            }
        }

        private RssFeed LoadIdleMode()
        {
            var menuItems = new List<MenuItem>
                              {
                                    new MenuItem
                                      {
                                          Name = Common.MOVIES_NAME,
                                          PluginMode = MenuItem.PluginMods.PLUGIN_MODE_MOVIES
                                      },
                                    new MenuItem
                                      {
                                          Name = Common.SERIES_NAME,
                                          PluginMode = MenuItem.PluginMods.PLUGIN_MODE_SERIES
                                      }
                                  
                              };
            return CreateMenuItemsFeed(menuItems);
        }

        private RssFeed LoadMoviesMenu()
        {
            var filterMenuItems = new List<MenuItem>
                              {
                                  new FilterMenuItem(
                                          "סרטים אחרונים",
                                          MenuItem.PluginMods.PLUGIN_MODE_MOVIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_LATEST),
                                  new FilterMenuItem(
                                          "כל הקטגוריות",
                                          MenuItem.PluginMods.PLUGIN_MODE_MOVIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_CATEGORY),
                                  new FilterMenuItem(
                                          "סינון מ-א עד ת",
                                          MenuItem.PluginMods.PLUGIN_MODE_MOVIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_A_TO_Z_HEB),
                                  new FilterMenuItem(
                                          "A TO Z",
                                          MenuItem.PluginMods.PLUGIN_MODE_MOVIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_A_TO_Z_ENG),
                                  new FilterMenuItem(
                                          "מדובבים",
                                          MenuItem.PluginMods.PLUGIN_MODE_MOVIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_HEB_DUB),
                                  new FilterMenuItem(
                                          "תרגום מובנה",
                                          MenuItem.PluginMods.PLUGIN_MODE_MOVIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_HEB_SUB),
                                  new FilterMenuItem(
                                          "סינון על פי אתרים",
                                          MenuItem.PluginMods.PLUGIN_MODE_MOVIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_SITE),
                                  new FilterMenuItem(
                                          "חיפוש סרט",
                                          MenuItem.PluginMods.PLUGIN_MODE_MOVIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_SEARCH)
                              };
            return CreateMenuItemsFeed(filterMenuItems);
        }

        private RssFeed LoadSeriesMenu()
        {
            var filterMenuItems = new List<MenuItem>
                              {
                                  new FilterMenuItem(
                                          "פרקים אחרונים",
                                          MenuItem.PluginMods.PLUGIN_MODE_SERIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_LATEST),
                                  new FilterMenuItem(
                                          "סינון על פי קטגוריה",
                                          MenuItem.PluginMods.PLUGIN_MODE_SERIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_CATEGORY),
                                  new FilterMenuItem(
                                          "סינון מ-א עד ת",
                                          MenuItem.PluginMods.PLUGIN_MODE_SERIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_A_TO_Z_HEB),
                                  new FilterMenuItem(
                                          "A TO Z",
                                          MenuItem.PluginMods.PLUGIN_MODE_SERIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_A_TO_Z_ENG),
                                  new FilterMenuItem(
                                          "סינון לפי סדרה",
                                          MenuItem.PluginMods.PLUGIN_MODE_SERIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_SERIES),
                                  new FilterMenuItem(
                                          "תרגום מובנה",
                                          MenuItem.PluginMods.PLUGIN_MODE_SERIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_HEB_SUB),
                                  new FilterMenuItem(
                                          "סינון על פי אתרים",
                                          MenuItem.PluginMods.PLUGIN_MODE_SERIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_SITE),
                                  new FilterMenuItem(
                                          "חיפוש סדרה",
                                          MenuItem.PluginMods.PLUGIN_MODE_SERIES,
                                          MenuItem.FilterTypes.FILTER_TYPES_SEARCH)
                              };
            return CreateMenuItemsFeed(filterMenuItems);
        }

        private RssFeed LoadFiltersMenus()
        {
            var pluginDBHandler = PluginDBHandler.Instance;

            switch (_filterType)
            {
                #region Category List
                case MenuItem.FilterTypes.FILTER_TYPES_CATEGORY:
                    {
                        var categories = pluginDBHandler.GetCategoriesList();
                        return CreateMenuItemsFeed(GetCategoriesMenuItems(categories));
                    }
                #endregion
                #region My Movies
                case MenuItem.FilterTypes.FILTER_TYPES_MY_MOVIES:
                    {
                        throw new NotImplementedException("FILTER_TYPES_MY_MOVIES not Implemented");
                    }
                #endregion
                #region My Series
                case MenuItem.FilterTypes.FILTER_TYPES_MY_SERIES:
                    {
                        throw new NotImplementedException("FILTER_TYPES_MY_SERIES not Implemented");
                    }
                #endregion
                #region Series
                case MenuItem.FilterTypes.FILTER_TYPES_SERIES:
                    {
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var seriesList = pluginDBHandler.GetSeriesList();
                            return CreateMenuItemsFeed(CreateSeriesMenuItems(seriesList));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region Latest
                case MenuItem.FilterTypes.FILTER_TYPES_LATEST:
                    {
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_MOVIES)
                        {
                            var videos = pluginDBHandler.GetLatestMoviesList();
                            return CreateMenuItemsFeed(CreateVideosMenuItems(videos));
                        }
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var tvShows = pluginDBHandler.GetLatestTVShowsList();
                            return CreateMenuItemsFeed(CreateTVShowsMenuItems(tvShows));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region A to Z Hebrew And English
                case MenuItem.FilterTypes.FILTER_TYPES_A_TO_Z_HEB:
                case MenuItem.FilterTypes.FILTER_TYPES_A_TO_Z_ENG:
                    {
                        InitializeAtoZList();
                        var aToZList = _filterType == MenuItem.FilterTypes.FILTER_TYPES_A_TO_Z_HEB
                                           ? _aTozListHeb
                                           : _aTozListEng;
                        var nextFilterType = _filterType == MenuItem.FilterTypes.FILTER_TYPES_A_TO_Z_HEB
                                           ? MenuItem.FilterTypes.FILTER_TYPES_A_Z_HEB_ID
                                           : MenuItem.FilterTypes.FILTER_TYPES_A_Z_ENG_ID;

                        var items = CreateAtoZFeed(aToZList, nextFilterType);
                        return CreateMenuItemsFeed(items);
                    }
                #endregion
                #region Hebrew Subtitle
                case MenuItem.FilterTypes.FILTER_TYPES_HEB_SUB:
                    {
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_MOVIES)
                        {
                            var videos = pluginDBHandler.GetHebSubMovies();
                            return CreateMenuItemsFeed(CreateVideosMenuItems(videos));
                        }
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var seriesList = pluginDBHandler.GetHebSubTVShows();
                            return CreateMenuItemsFeed(CreateSeriesMenuItems(seriesList));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region Hebrew Deubbed
                case MenuItem.FilterTypes.FILTER_TYPES_HEB_DUB:
                    {
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_MOVIES)
                        {
                            var videos = pluginDBHandler.GetHebDubMovies();
                            return CreateMenuItemsFeed(CreateVideosMenuItems(videos));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region Site List
                case MenuItem.FilterTypes.FILTER_TYPES_SITE:
                    {
                        var sites = pluginDBHandler.GetSitesNames();
                        return CreateMenuItemsFeed(CreateSitesMenuItems(sites));
                    }
                #endregion
                #region Search
                case MenuItem.FilterTypes.FILTER_TYPES_SEARCH:
                    {
                        string searchText = Utils.GetParam(this._queryStringParams, Common.SEARCH_TEXT, string.Empty);
                        if(string.IsNullOrEmpty(searchText))
                        {
                            var searchMenuItem = new SearchMenuItem(_pluginMode, _filterType);
                            return CreateMenuItemsFeed(new List<MenuItem> {searchMenuItem});
                        }
                        searchText = Utils.LoopDecodeUrl(searchText);
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_MOVIES)
                        {
                            var videos = pluginDBHandler.GetMoviesBySearchText(searchText);
                            return CreateMenuItemsFeed(CreateVideosMenuItems(videos));
                        }
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var tvShows = pluginDBHandler.GetTVShowsBySearchText(searchText);
                            return CreateMenuItemsFeed(CreateSeriesMenuItems(tvShows));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region Category IDs
                case MenuItem.FilterTypes.FILTER_TYPES_CATEGORY_ID:
                    {
                        var categoryId = Utils.GetParam(this._queryStringParams, Common.CATEGORY_ID, 0);
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_MOVIES)
                        {
                            var videos = pluginDBHandler.GetMoviesByCategoryId(categoryId);
                            return CreateMenuItemsFeed(CreateVideosMenuItems(videos));
                        }
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var tvShows = pluginDBHandler.GetTVShowsByCategoryId(categoryId);
                            return CreateMenuItemsFeed(CreateTVShowsMenuItems(tvShows));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region A to Z Heberew And English Ids
                case MenuItem.FilterTypes.FILTER_TYPES_A_Z_HEB_ID:
                case MenuItem.FilterTypes.FILTER_TYPES_A_Z_ENG_ID:
                    {
                        InitializeAtoZList();
                        var aToZList = _filterType == MenuItem.FilterTypes.FILTER_TYPES_A_Z_HEB_ID
                                           ? _aTozListHeb
                                           : _aTozListEng;

                        var atoZId = Utils.GetParam(this._queryStringParams, Common.A_TO_Z_ID, 0);
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_MOVIES)
                        {
                            var videos = pluginDBHandler.GetAtoZMoviesList(aToZList[atoZId]);
                            return CreateMenuItemsFeed(CreateVideosMenuItems(videos));
                        }
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var seriesList = pluginDBHandler.GetAtoZSeriesList(aToZList[atoZId]);
                            return CreateMenuItemsFeed(CreateSeriesMenuItems(seriesList));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region Series Ids
                case MenuItem.FilterTypes.FILTER_TYPES_SERIES_ID:
                    {
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var seriesId = Utils.GetParam(this._queryStringParams, Common.SERIES_ID, 0);
                            var hebSubFilter = Utils.GetParam(this._queryStringParams, Common.HEB_SUB_FILTER, (int)SeriesMenuItem.HebSubFilter.NO_FILTER);
                            var siteId = Utils.GetParam(this._queryStringParams, Common.SITE_ID, 0);

                            if (hebSubFilter != (int)SeriesMenuItem.HebSubFilter.NO_FILTER)
                            {
                                var filter1 = pluginDBHandler.GetHebSubSeasonsbySeriesId(seriesId);
                                return CreateMenuItemsFeed(CreateSeasonsNumbersMenuItems(seriesId, filter1));
                            }
                            if (siteId != 0)
                            {
                                var filter2 = pluginDBHandler.GetSeasonsbySeriesAndSiteId(siteId, seriesId);
                                return CreateMenuItemsFeed(CreateSeasonsNumbersMenuItems(seriesId, filter2));
                            }

                            var seasonsNumbersList = pluginDBHandler.GetSeasonsbySeriesId(seriesId);
                            return CreateMenuItemsFeed(CreateSeasonsNumbersMenuItems(seriesId, seasonsNumbersList));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region Season Ids
                case MenuItem.FilterTypes.FILTER_TYPES_SEASON_NUMBER:
                    {
                        var seriesId = Utils.GetParam(this._queryStringParams, Common.SERIES_ID, 0);
                        var seasonNumber = Utils.GetParam(this._queryStringParams, Common.SEASON_NUMBER, 0);
                        var hebSubFilter = Utils.GetParam(this._queryStringParams, Common.HEB_SUB_FILTER, (int)SeriesMenuItem.HebSubFilter.NO_FILTER);
                        var siteId = Utils.GetParam(this._queryStringParams, Common.SITE_ID, 0);

                        if (hebSubFilter != (int)SeriesMenuItem.HebSubFilter.NO_FILTER)
                        {
                            var filter1 = pluginDBHandler.GetHebSubTVShowsBySeasonId(seriesId, seasonNumber);
                            return CreateMenuItemsFeed(CreateTVShowsMenuItems(filter1));
                        }
                        if (siteId != 0)
                        {
                            var filter2 = pluginDBHandler.GetTVShowsBySeasonAndSiteId(siteId, seriesId, seasonNumber);
                            return CreateMenuItemsFeed(CreateTVShowsMenuItems(filter2));
                        }

                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var tvShows = pluginDBHandler.GetTVShowsBySeasonId(seriesId, seasonNumber);
                            return CreateMenuItemsFeed(CreateTVShowsMenuItems(tvShows));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region Site Id
                case MenuItem.FilterTypes.FILTER_TYPES_SITE_ID:
                    {
                        var siteId = Utils.GetParam(this._queryStringParams, Common.SITE_ID, 0);
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_MOVIES)
                        {
                            var videos = pluginDBHandler.GetMoviesBySite(siteId);
                            return CreateMenuItemsFeed(CreateVideosMenuItems(videos));
                        }
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var seriesTVShows = pluginDBHandler.GetTVShowsBySite(siteId);
                            return CreateMenuItemsFeed(CreateSeriesMenuItems(seriesTVShows));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region Movie Id
                case MenuItem.FilterTypes.FILTER_TYPES_MOVIE_ID:
                    {
                        var videoId = Utils.GetParam(this._queryStringParams, Common.VIDEO_ID, 0);
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_MOVIES)
                        {
                            var video = pluginDBHandler.GetMovieByID(videoId);
                            return CreateMenuItemsFeed(CreateVideoLinksMenuItems(video));
                        }
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var tvShow = pluginDBHandler.GetTVShowByID(videoId);
                            return CreateMenuItemsFeed(CreateTVShowLinksMenuItems(tvShow));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region Link Id
                case MenuItem.FilterTypes.FILTER_TYPES_LINK_ID:
                    {
                        var linkId = Utils.GetParam(this._queryStringParams, Common.LINK_ID, 0);
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_MOVIES)
                        {
                            var videoLink = pluginDBHandler.GetVideoLinkByID(linkId);
                            return CreateMenuItemsFeed(
                                        CreateExtractedVideoLinkMenuItems(
                                            videoLink.LinkURL,
                                            videoLink.Video.VideoName,
                                            videoLink.Video.ImageUrl));
                        }
                        if (_pluginMode == MenuItem.PluginMods.PLUGIN_MODE_SERIES)
                        {
                            var tvShowlink = pluginDBHandler.GetTVShowLinkByID(linkId);
                            return CreateMenuItemsFeed(
                                        CreateExtractedVideoLinkMenuItems(
                                            tvShowlink.LinkURL,
                                            tvShowlink.TVShow.Name,
                                            tvShowlink.TVShow.ImageUrl));
                        }
                        throw new Exception(string.Format("Unknown pluginMode arraive at filter: {0}", _filterType));
                    }
                #endregion
                #region Default swith mode
                default:
                    {
                        throw new ArgumentException("Got unknow FilterType");
                    }
                #endregion
            }
        }
        #endregion

        #region Feeds
        private RssFeed CreateMenuItemsFeed(ICollection<MenuItem> menuItems)
        {
            try
            {
                var feed = LoadFromCache();
                if (feed != null) return feed;

                var rssChannel = new RssChannel
                {
                    Title = "Movies Channel",
                    Description = "Movies List",
                    Link = new Uri(string.Format("{0}", Utils.GetSiteUrl())),
                    Language = "he"
                };

                rssChannel.LastBuildDate = rssChannel.Items.LatestPubDate();

                foreach (var menuItem in menuItems)
                {
                    rssChannel.Items.Add(menuItem.CreateRssItem());
                }

                if (menuItems.Count == 0)
                {
                    var rssItem = new RssItem
                    {
                        Title = "לא נמצאו תוצאות",
                        Description = "לא נמצאו תוצאות",
                        PubDate = DateTime.Now,
                        Link = new Uri(string.Format("{0}", Utils.GetSiteUrl()))
                    };

                    rssChannel.Items.Add(rssItem);
                }

                feed = new RssFeed { Encoding = Encoding.UTF8 };
                feed.Channels.Add(rssChannel);

                AddToCache(feed);

                return feed;
            }
            catch (Exception ex)
            {
                return CreateErrorResponse(ex.Message);
            }
        }

        private List<MenuItem> GetCategoriesMenuItems(IEnumerable<Category> categories)
        {
            return categories.Select(category =>
                new CategoryMenuItem(category, _pluginMode))
                .Cast<MenuItem>().ToList();
        }

        private List<MenuItem> CreateVideosMenuItems(ICollection<Video> videos)
        {
            var menuItems = videos.Page(this._pageNumber, PAGE_SIZE).
                                        Select(video => new MovieMenuItem(video, _pluginMode)).
                                        Cast<MenuItem>().ToList();

            if ((this._pageNumber * PAGE_SIZE) <= videos.Count)
            {
                menuItems.Add(new NextPageMenuItem(_queryStringParams, _pageNumber));
            }
            return menuItems;
        }

        private List<MenuItem> CreateTVShowsMenuItems(ICollection<TVShow> tvShows)
        {
            var menuItems = tvShows.Page(this._pageNumber, PAGE_SIZE).
                                        Select(tvShow => new TVShowMenuItem(tvShow, _pluginMode)).
                                        Cast<MenuItem>().ToList();

            if ((this._pageNumber * PAGE_SIZE) <= tvShows.Count)
            {
                menuItems.Add(new NextPageMenuItem(_queryStringParams, _pageNumber));
            }
            return menuItems;
        }

        private List<MenuItem> CreateSeriesMenuItems(IEnumerable<Series> seriesList)
        {
            var siteId = Utils.GetParam(this._queryStringParams, Common.SITE_ID, 0);
            int hebSubFilter;
            if (_filterType == MenuItem.FilterTypes.FILTER_TYPES_HEB_SUB)
            {
                hebSubFilter = (int)SeriesMenuItem.HebSubFilter.TAKE_HEB_SUB;
            }
            else
            {
                hebSubFilter = Utils.GetParam(
                                    this._queryStringParams,
                                    Common.HEB_SUB_FILTER,
                                    (int)SeriesMenuItem.HebSubFilter.NO_FILTER);
            }

            List<MenuItem> menuItems;
            if (siteId != 0)
            {
                menuItems = seriesList.Select(series => new SeriesMenuItem(siteId, series, _pluginMode)).
                                        Cast<MenuItem>().ToList();
                return menuItems;
            }
            if (hebSubFilter != (int)SeriesMenuItem.HebSubFilter.NO_FILTER)
            {
                menuItems = seriesList.Select(series => new SeriesMenuItem(series, (SeriesMenuItem.HebSubFilter)hebSubFilter, _pluginMode)).
                                        Cast<MenuItem>().ToList();
                return menuItems;
            }
            menuItems = seriesList.Select(series => new SeriesMenuItem(series, _pluginMode)).
                                    Cast<MenuItem>().ToList();
            return menuItems;
        }

        private List<MenuItem> CreateSeasonsNumbersMenuItems(long seriesId, IEnumerable<long> seasonsNumbersList)
        {
            var siteId = Utils.GetParam(this._queryStringParams, Common.SITE_ID, 0);
            int hebSubFilter;
            if (_filterType == MenuItem.FilterTypes.FILTER_TYPES_HEB_SUB)
            {
                hebSubFilter = (int)SeriesMenuItem.HebSubFilter.TAKE_HEB_SUB;
            }
            else
            {
                hebSubFilter = Utils.GetParam(
                                    this._queryStringParams,
                                    Common.HEB_SUB_FILTER,
                                    (int)SeriesMenuItem.HebSubFilter.NO_FILTER);
            }

            List<MenuItem> menuItems;
            if (siteId != 0)
            {
                menuItems = seasonsNumbersList.Select(seasonNumber => new SeasonsNumberMenuItem(siteId, seriesId, seasonNumber, _pluginMode)).
                                        Cast<MenuItem>().ToList();
                return menuItems;
            }
            if (hebSubFilter != (int)SeriesMenuItem.HebSubFilter.NO_FILTER)
            {
                menuItems = seasonsNumbersList.Select(seasonNumber => new SeasonsNumberMenuItem(seriesId, seasonNumber, (SeriesMenuItem.HebSubFilter)hebSubFilter, _pluginMode)).
                                        Cast<MenuItem>().ToList();
                return menuItems;
            }

            menuItems = seasonsNumbersList.Select(seasonNumber => new SeasonsNumberMenuItem(seriesId, seasonNumber, _pluginMode)).
                                        Cast<MenuItem>().ToList();
            return menuItems;
        }

        private List<MenuItem> CreateSitesMenuItems(IEnumerable<Site> sites)
        {
            return sites.Select(site => new SiteMenuItem(site, _pluginMode)).Cast<MenuItem>().ToList();
        }

        private List<MenuItem> CreateAtoZFeed(IEnumerable<KeyValuePair<int, string>> items, MenuItem.FilterTypes filterType)
        {
            return items.Select(item => new AtoZMenuItem(item, this._pluginMode, filterType)).Cast<MenuItem>().ToList();
        }

        private List<MenuItem> CreateVideoLinksMenuItems(Video video)
        {
            var menuItems = new List<MenuItem>();

            foreach (var videoLink in video.VideosLinks)
            {
                videoLink.SourceReference.Load();
                var menuItem = new VideoLinkMenuItem(videoLink, _pluginMode);
                menuItems.Add(menuItem);
            }

            return menuItems;
        }

        private List<MenuItem> CreateTVShowLinksMenuItems(TVShow tvShow)
        {
            var menuItems = new List<MenuItem>();

            foreach (var tvShowLink in tvShow.TVShowsLinks)
            {
                tvShowLink.SourceReference.Load();
                var menuItem = new TVShowLinkMenuItem(tvShowLink, _pluginMode);
                menuItems.Add(menuItem);
            }

            return menuItems;
        }

        private List<MenuItem> CreateExtractedVideoLinkMenuItems(string linkUrl, string videoName, string imageUrl)
        {
            var menuItems = new List<MenuItem>();

            var videoResult = this.ExtractVideoFullLink(linkUrl);
            if (videoResult == null || !videoResult.IsValid)
            {
                throw new Exception(string.Format("Unknown video link: {0}", linkUrl));
            }

            menuItems.Add(new ExtractedLinkMenuItem(videoName, imageUrl, videoResult));
            return menuItems;
        }
        #endregion

        #region Helper Methods
        private void InitializeAtoZList()
        {
            _aTozListHeb.Add(1, "א");
            _aTozListHeb.Add(2, "ב");
            _aTozListHeb.Add(3, "ג");
            _aTozListHeb.Add(4, "ד");
            _aTozListHeb.Add(5, "ה");
            _aTozListHeb.Add(6, "ו");
            _aTozListHeb.Add(7, "ז");
            _aTozListHeb.Add(8, "ח");
            _aTozListHeb.Add(9, "ט");
            _aTozListHeb.Add(10, "י");
            _aTozListHeb.Add(11, "ע");
            _aTozListHeb.Add(12, "ל");
            _aTozListHeb.Add(13, "מ");
            _aTozListHeb.Add(14, "נ");
            _aTozListHeb.Add(15, "ס");
            _aTozListHeb.Add(16, "ע");
            _aTozListHeb.Add(17, "פ");
            _aTozListHeb.Add(18, "צ");
            _aTozListHeb.Add(19, "ק");
            _aTozListHeb.Add(20, "ר");
            _aTozListHeb.Add(21, "ש");
            _aTozListHeb.Add(22, "ת");

            _aTozListEng.Add(1, "A");
            _aTozListEng.Add(2, "B");
            _aTozListEng.Add(3, "C");
            _aTozListEng.Add(4, "D");
            _aTozListEng.Add(5, "E");
            _aTozListEng.Add(6, "F");
            _aTozListEng.Add(7, "G");
            _aTozListEng.Add(8, "H");
            _aTozListEng.Add(9, "I");
            _aTozListEng.Add(10, "J");
            _aTozListEng.Add(11, "K");
            _aTozListEng.Add(12, "L");
            _aTozListEng.Add(13, "M");
            _aTozListEng.Add(14, "N");
            _aTozListEng.Add(15, "O");
            _aTozListEng.Add(16, "P");
            _aTozListEng.Add(17, "Q");
            _aTozListEng.Add(18, "R");
            _aTozListEng.Add(19, "S");
            _aTozListEng.Add(20, "T");
            _aTozListEng.Add(21, "U");
            _aTozListEng.Add(22, "V");
            _aTozListEng.Add(23, "W");
            _aTozListEng.Add(24, "X");
            _aTozListEng.Add(25, "Y");
            _aTozListEng.Add(26, "Z");
        }

        private VideoResult ExtractVideoFullLink(string url)
        {
            if (VideoBBExtractor.IsContainVideoLink(url))
            {
                return VideoBBExtractor.ExtractMovieUrl(url);
            }

            if (VideozerExtractor.IsContainVideoLink(url))
            {
                return VideozerExtractor.ExtractMovieUrl(url);
            }

            if (MytubeExtractor.IsContainVideoLink(url))
            {
                return MytubeExtractor.ExtractMovieUrl(url);
            }

            if (SdarotOrgExtractor.IsContainVideoLink(url))
            {
                return SdarotOrgExtractor.ExtractMovieUrl(url);
            }

            if (MultiUploadExtractor.IsContainVideoLink(url))
            {
                return MultiUploadExtractor.ExtractMovieUrl(url);
            }

            if (MegaVideoExtractor.IsContainVideoLink(url))
            {
                return MegaVideoExtractor.ExtractMovieUrl(url);
            }

            if (CuevanaTVExtractor.IsContainVideoLink(url))
            {
                return CuevanaTVExtractor.ExtractMovieUrl(url);
            }

            return null;
        }

        private RssFeed CreateErrorResponse(string errorMessage)
        {
            var channel = new RssChannel
            {
                Title = "שגיאה",
                Description = "Error Message",
                Language = "he"
            };
            channel.LastBuildDate = channel.Items.LatestPubDate();

            var item = new RssItem
            {
                Title = "Error",
                Description = errorMessage,
                PubDate = DateTime.Now,
                Comments = "Error"
            };

            channel.Items.Add(item);

            var feed = new RssFeed { Encoding = Encoding.UTF8 };
            feed.Channels.Add(channel);
            return feed;
        }

        private void AddToCache(RssFeed rssFeed)
        {
            if (_cacheManager.IsInCache(this.Url)) return;

            _cacheManager.CacheData(this.Url, rssFeed, DateTime.UtcNow.AddMinutes(30));
        }

        private RssFeed LoadFromCache()
        {
            if (_cacheManager.IsInCache(this.Url))
            {
                var rssFeed = _cacheManager.GetData(this.Url) as RssFeed;
                if (rssFeed != null)
                {
                    return rssFeed;
                }
            }
            return null;
        }
        #endregion
        #endregion
    }
}